﻿#pragma once
#include <QQuickItem>
#include <QImage>
#include <QMutex>

class QSGSimpleTextureNode;
class QSGTexture;
class VideoItem: public QQuickItem
{
	Q_OBJECT
	QML_ELEMENT
	Q_PROPERTY(bool playing READ playing NOTIFY playingChanged)
	Q_PROPERTY(bool hasError READ hasError NOTIFY errorChanged)
	Q_PROPERTY(QString source READ source WRITE setSource NOTIFY sourceChanged)
	Q_PROPERTY(bool autoPlayAsSourceChanged READ autoPlayAsSourceChanged WRITE setAutoPlayAsSourceChanged NOTIFY setAutoPlayAsSourceChangedChanged)
public:
	explicit VideoItem(QQuickItem* parent = nullptr);
	~VideoItem();
	bool playing() const;
	bool hasError() const;
	QString source() const;
	void setSource(QString const& source);
	bool autoPlayAsSourceChanged() const;
	void setAutoPlayAsSourceChanged(bool autoPlayAsSourceChanged);

public slots:
	bool play();
	void stop();
signals:
	void urlChanged();
	void errorOccurred();
	void playingChanged();
	void errorChanged();
	void sourceChanged();
	void setAutoPlayAsSourceChangedChanged();
protected:
	void drawFrame();
	QSGNode* updatePaintNode(QSGNode*, UpdatePaintNodeData*) override;
	void geometryChange(const QRectF& newGeometry, const QRectF& oldGeometry) override;
	void cleanup();
private:
	static void* lock(void* data, void** p_pixels);
	static void unlock(void* data, void* id, void* const* p_pixels);
	static void display(void* data, void* id);
	static void error(const struct libvlc_event_t* p_event, void* data);
	static void onPlaying(const struct libvlc_event_t* p_event, void* data);
	static void onStopped(const struct libvlc_event_t* p_event, void* data);
private:
	QString m_source;
	bool m_autoPlayAsSourceChanged = false;
	bool m_geometryChanged = true;
	bool m_frameChanged = true;
	QSGSimpleTextureNode* m_node = nullptr;
	uint8_t* m_pPixelData = nullptr;
	QSGTexture* m_texture = nullptr;
	QImage m_image;
	QMutex m_mutex;
	struct libvlc_instance_t* m_vlc = nullptr;
	struct libvlc_media_player_t* m_mp = nullptr;
	struct libvlc_media_t* m_media = nullptr;
	bool m_playing = false;
	bool m_hasError = false;
};
